<html lang="en">
<head>
    <title>Deskovery Map</title>
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        body, html {
            height: 100%;
            background-color: darkgrey
        }

        #mapcanvas {
            width: 96vh;
            height: 96vh;
            background-color: lightskyblue;
            margin: 2vh
        }

        #data {
            position: absolute;
            width: 20em;
            /*height: 10vw;*/
            background-color: lightyellow;
            opacity: 0.3;
            top: 0;
            left: 0;
            margin: 2vh;
            font-family: monospace;
        }
    </style>
</head>
<body style="">
<canvas id="mapcanvas" width="1000" height="1000"></canvas>
<div id="data">
    <pre id="ctrl">--No Data--</pre>
    <a href="/archive">*Archive*</a>
    <hr/>
    <div id="mapList"></div>
</div>
<script>

    function drawMap(bounds, mapArray) {
        bounds.ctx.beginPath();
        bounds.ctx.strokeStyle = "#303030";
        for (let i = 0; i < mapArray.length; i++) {
            const d = mapArray[i];
            let x = bounds.screenX(d.x);
            let y = bounds.screenY(d.y);
            if (i === 0) {
                bounds.ctx.moveTo(x, y);
            } else {
                bounds.ctx.lineTo(x, y)
            }
            if (i === mapArray.length - 1) {
                bounds.ctx.stroke();
                bounds.ctx.beginPath();
                bounds.ctx.strokeStyle = "#00FF00"
                bounds.ctx.arc(x, y, 20, 0, Math.PI * 2);
                bounds.ctx.stroke();
            }

        }
    }

    function drawDirections(bounds, mapArray) {
        let dist = bounds.diagonal / 15;
        for (d of mapArray) {
            let dx = dist * Math.cos(d.theta);
            let dy = dist * Math.sin(d.theta);
            bounds.ctx.beginPath();
            bounds.ctx.strokeStyle = "#FFFF00";
            bounds.ctx.moveTo(bounds.screenX(d.x), bounds.screenY(d.y));
            bounds.ctx.lineTo(bounds.screenX(d.x + dx), bounds.screenY(d.y + dy));
            bounds.ctx.stroke()
        }
    }

    function drawObstacles(bounds, obstacles) {
        let dist = bounds.diagonal / 100;
        for (obstacle of obstacles) {

            let dx = dist * Math.cos(obstacle.angle + Math.PI / 2);
            let dy = dist * Math.sin(obstacle.angle + Math.PI / 2);
            bounds.ctx.beginPath();
            bounds.ctx.strokeStyle = "#FF0000";

            bounds.ctx.moveTo(bounds.screenX(obstacle.x - dx), bounds.screenY(obstacle.y - dy));
            bounds.ctx.lineTo(bounds.screenX(obstacle.x + dx), bounds.screenY(obstacle.y + dy));
            bounds.ctx.stroke()
        }
    }

    function drawMapData(mapArray) {
        let ctx = document.getElementById("mapcanvas").getContext("2d");
        let maxX = -1e99;
        let maxY = -1e99;
        let minX = 1e99;
        let minY = 1e99;
        let obstacles = [];
        for (d of mapArray) {
            maxX = Math.max(maxX, d.x);
            maxY = Math.max(maxY, d.y);
            minX = Math.min(minX, d.x);
            minY = Math.min(minY, d.y);
            if (d.dto >= 0) {
                d.theta = d.th / 180 * Math.PI;
                let obstacle = {
                    x: d.x + d.dto * Math.cos(d.theta),
                    y: d.y + d.dto * Math.sin(d.theta),
                    visX: d.x,
                    visY: d.y,
                    angle: d.theta
                };
                maxX = Math.max(maxX, obstacle.x);
                maxY = Math.max(maxY, obstacle.y);
                minX = Math.min(minX, obstacle.x);
                minY = Math.min(minY, obstacle.y);
                obstacles.push(obstacle);
            }
        }
        let linearSize = Math.sqrt(Math.max(10000, (maxX - minX) * (maxX - minX), (maxY - minY) * (maxY - minY)));
        const bounds = {
            ctx: ctx,
            canvas: ctx.canvas,
            width: linearSize * 1.2,
            left: minX - linearSize / 10,
            height: linearSize * 1.2,
            top: maxY + linearSize / 10,
            screenX: function (x) {
                return this.canvas.width * (x - this.left) / this.width;
            },
            screenY: function (y) {
                return this.canvas.height * (this.top - y) / this.height;
            }
        };
        bounds.diagonal = Math.sqrt(bounds.width * bounds.width + bounds.height * bounds.height);
        bounds.ctx.clearRect(0, 0, bounds.canvas.width, bounds.canvas.height);
        drawMap(bounds, mapArray);
        drawDirections(bounds, mapArray);
        drawObstacles(bounds, obstacles);
    }

    function drawMapSelector(mapList, currentMap) {
        let s = "--Live--";
        if ("" !== currentMap) {
            s = "<p></p><a href=\"../../../..\">" + s + "</a></p>";
        }
        for (map of mapList) {
            if (("?" + map) !== currentMap) {
                s += "<p><a href=\"?" + map + "\">" + map + "</a></p>"
            } else {
                s += "<p>" + map + "</p>";
            }
        }
        document.getElementById("mapList").innerHTML = s;
    }

    const liveUpdate = function () {
        fetch("/map-data" + document.location.search)
            .then(function (response) {
                response.json().then(function (bodyData) {
                    drawMapData(bodyData["mapData"]);
                    drawMapSelector(bodyData["maps"], document.location.search);
                })
            })
            .catch(function (reason) {
                console.warn(reason)
            });
        if (document.location.search === "") {
            window.setTimeout(liveUpdate, 200);
        }
    };
    liveUpdate();
    var lastX = 0.0;
    var lastY = 0.0;
    var lb1 = false;
    var lb2 = false;
    var lb3 = false;
    var lb4 = false;

    setInterval(function () {
        var gamepads = navigator.getGamepads();
        var gp = gamepads[0];
        if (gp) {
            var axes = gp.axes;
            var b1 = gp.buttons[0] !== undefined && gp.buttons[0].pressed;
            var b2 = gp.buttons[1] !== undefined && gp.buttons[1].pressed;
            var b3 = gp.buttons[2] !== undefined && gp.buttons[2].pressed;
            var b4 = gp.buttons[3] !== undefined && gp.buttons[3].pressed;
            var x = axes[1];
            var y = axes.length > 5 ? axes[5] : axes[axes.length - 1];
            if (x !== lastX || y !== lastY || lb1 !== b1 || lb2 !== b2 || lb3 !== b3 || lb4 !== b4) {
                lastX = x;
                lastY = y;
                lb1 = b1;
                lb2 = b2;
                lb3 = b3;
                lb4 = b4;
                const b = function b(q) {
                    return q ? "X" : "."
                };
                document.getElementById("ctrl").innerText =
                    "[" + x.toFixed(2).padStart(5) + "; " + (y).toFixed(2).padStart(5) + "] " +
                    b(b1) + b(b2) + b(b3) + b(b4);
                fetch("/control?x=" + x + "&y=" + y + "&b1=" + b1 + "&b2=" + b2 + "&b3=" + b3 + "&b4=" + b4,)
                    .catch(function (reason) {
                        console.warn(reason);
                    });
            }
        }
    }, 50)

</script>
</body>
</html>